﻿#include "guild_service_basic.h"

#include "GuildMember_struct.h"
#include "GuildModuleMembers_struct.h"

#include "guild/guild_loader.hpp"
#include "guild/guild_saver.hpp"
#include "guild/module/guild_module_loader.hpp"
#include "guild/guild_redis_key_def.h"
#include "util/util.hh"

namespace guild_service {
// const Guild *GuildServiceBasic::GetGuild(const guild_id_type guild_id) const {
//   auto iter = guilds_.find(guild_id);
//   if (iter == guilds_.end()) {
//     return nullptr;
//   }

//   return &(iter->second);
// }

// const Guild *GuildServiceBasic::GetGuildByRole(const role_uuid_type role_uuid) {
//   guild_id_type guild_id = GetGuildIdByRole(role_uuid);
//   if (guild_id == kInvalidGuildId) {
//     return nullptr;
//   }
//   return GetGuild(guild_id);
// }

guild_id_type GuildServiceBasic::GetGuildIdByRole(
    const role_uuid_type role_uuid) const {
  auto it = role_to_guild_dic_.find(role_uuid);
  if (it != role_to_guild_dic_.end()) {
    return it->second;
  }
  guild_id_type guild_id = kInvalidGuildId;
  if (!GetGuildIdByRoleFromRedis(role_uuid, guild_id)) {
    return kInvalidGuildId;
  }
  return guild_id;
}

bool GuildServiceBasic::GetGuildIdByRoleFromRedis(
    const role_uuid_type role_uuid, guild_id_type &guild_id) const {
  return detail::LoadGuildIdByRole(kGuildServiceBasicName, role_uuid, guild_id);
}

bool GuildServiceBasic::AddGuild(const guild_id_type &guild_id) {
  LOG_DEBUG("添加公会 公会id:%llu", guild_id);

  return guild_set_.emplace(guild_id).second;
}

bool GuildServiceBasic::RemoveGuild(const guild_id_type guild_id) {
  LOG_DEBUG("移除公会 公会id:%llu", guild_id);
  // TODO mutex
  return guild_set_.erase(guild_id) > 0;
}

bool GuildServiceBasic::AddGuildRole(const guild_id_type guild_id,
                                     const role_uuid_type role_uuid) {
  LOG_DEBUG("添加公会角色 角色唯一id:%llu 公会id:%llu", role_uuid, guild_id);

  return role_to_guild_dic_.emplace(role_uuid, guild_id).second;
}

bool GuildServiceBasic::LoadGuildAsync() {
  // if (!LoadGuildIdAsync()) {
  //   LOG_FAIL("异步加载公会id失败");
  //   return false;
  // }

  if (!LoadGuildModuleAsync()) {
    LOG_FAIL("异步加载公会模块失败");
    return false;
  }

  return true;
}

static std::vector<std::string> split_str;

bool GuildServiceBasic::LoadGuildIdAsync() {
  return guild_service::detail::LoadAllGuildIdAsync(
      kGuildServiceBasicName,
      [](const std::vector<std::string> &guild_str_list) {
        for (const auto &str : guild_str_list) {
          split_str.clear();

          // UtilSingleton()->splitBy(str, ':', split_str);
          UtilSingleton().splitBy(str, ':', split_str);
          if (split_str.size() >= 2) {
            // LOG_DEBUG("获取公会id 键:%s", str.c_str());
            guild_id_type guild_id = std::stoull(split_str[1]);
            // Guild guild = GuildServiceBasic::NewGuild(guild_id);
            GuildServiceBasicSingleton->AddGuild(guild_id);
          } else {
            LOG_FAIL("字符串分割失败 键:%s", str.c_str());
          }
        }
      });
}

bool GuildServiceBasic::LoadGuildModuleAsync() {
  auto load_brief_cb =
      std::bind(&GuildServiceBasic::LoadGuildModuleBriefCallback, this,
                std::placeholders::_1, std::placeholders::_2);

  ForeachGuild([load_brief_cb](const guild_id_type &guild_id) {
    detail::GetGuildModuleAsync<GuildModuleBrief>(kGuildServiceBasicName, guild_id,
                                            kGuildModuleBriefName, load_brief_cb);

    // detail::GetGuildModuleAsync<GuildMembers>(kGuildServiceBasicName, guild_id,
    //                                           kGuildModuleMembersName);
  });
  return true;
}

static std::string sPbStr;
void GuildServiceBasic::LoadGuildModuleBriefCallback(const redis_result_type &result, std::uint64_t udata) {
  if (!result.is_success()) {
    LOG_FAIL("redis处理失败 命令:%s 错误:%s 错误码:%d",
             result.get_command().c_str(), result.get_error().c_str(),
             static_cast<int32_t>(result.get_error_code()));
    return;
  }

  if (redis_reply_is_nil(result)) {
    LOG_DEBUG("redis回复是nil 命令:%s", result.get_command().c_str());
    return;
  }

  // std::string pb_str;
  if (!result.get_return(sPbStr)) {
    LOG_FAIL("redis获取返回值失败 命令:%s", result.get_command().c_str());
    return;
  }
#ifdef DEBUG
  assert(!sPbStr.empty());
#endif  // DEBUG

  const std::string pb_str_decode = base64_decode(sPbStr);

  GuildModuleBrief module_brief;
  if (!detail::DeserializeFromString(pb_str_decode, module_brief)) {
    LOG_FAIL("公会模块序列化失败 命令:(%s)", result.get_command().c_str());
    return;
  }

  // TODO lock guard

  auto &guild_id = udata;
  guild_to_brief_dic_.emplace(guild_id, module_brief);

  // LOG_DEBUG("redis异步加载公会模块成功 命令:%s 模块名:%s",
  //     result.get_command().c_str(), Serializer::kModuleName);
}

bool GuildServiceBasic::IncrGuildLastId(guild_id_type &guild_id) {
  return detail::IncrGuildGeneralId(kGuildServiceBasicName,
                                    detail::kLoadGuildLastIdKey, guild_id);
}

bool GuildServiceBasic::SaveGuildRoleToRedis(const std::string &op,
                                             const role_uuid_type role_uuid,
                                             const guild_id_type guild_id) {
  return detail::SaveGuildIdByRole(kGuildServiceBasicName, op, role_uuid,
                                   guild_id);
}

bool GuildServiceBasic::SaveLastGuildIdToRedis(const guild_id_type guild_id) {
  return detail::SaveLastGuildId(kGuildServiceBasicName, guild_id);
}

bool GuildServiceBasic::RemoveGuildRole(const guild_id_type guild_id,
                                        const role_uuid_type role_uuid) {
  LOG_DEBUG("公会id:%llu 角色唯一id:%llu 移除公会角色", guild_id, role_uuid);

  return role_to_guild_dic_.erase(role_uuid) > 0;
}

Guild GuildServiceBasic::NewGuild(const guild_id_type guild_id /* = 0ull*/) {
  Guild guild;

  if (guild_id != 0) {
    guild.id = guild_id;
  } else {
    if (!GuildServiceBasic::IncrGuildLastId(guild.id)) {
      guild.id = kInvalidGuildId;
      return guild;
    }
  }

  guild.pool_index = guild_service::detail::NewPoolIndex();

  return guild;
}

bool GuildServiceBasic::InSameGuild(const role_uuid_type role_uuid1,
                                    const role_uuid_type role_uuid2) {
  guild_id_type guild_id1 = GetGuildIdByRole(role_uuid1);
  guild_id_type guild_id2 = GetGuildIdByRole(role_uuid2);
  if (guild_id1 == kInvalidGuildId || guild_id2 == kInvalidGuildId) {
    return false;
  }

  if (guild_id1 == kInvalidGuildId || guild_id2 == kInvalidGuildId) {
    return false;
  }

  return guild_id1 == guild_id2;
}

bool GuildServiceBasic::IsValidGuild(const Guild &guild) {
  return guild.id != kInvalidGuildId && guild.pool_index != kInvalidPoolIndex;
}

bool GuildServiceBasic::HasGuild(const role_uuid_type role_uuid) const {
  return role_to_guild_dic_.count(role_uuid) > 0;
}

bool GuildServiceBasic::IsGuildNameExisted(const std::string &name) const {
  // for (auto it : guilds_) {
  //   const auto &guild = it.second;
  //   const auto *guild_brief_ptr = detail::GetGuildModule<GuildBrief>(
  //       kGuildServiceBasicName, guild, kGuildModuleBriefName,
  //       GetModulePriority::GET_MODULE_PRI_USE_CACHE);
  //   if (guild_brief_ptr && guild_brief_ptr->name == name) {
  //     return true;
  //   }
  // }

  for (const auto &it: guild_to_brief_dic_) {
    if (it.second.name == name) {
      return true;
    }
  }

  return false;
}

void GuildServiceBasic::ForeachGuild(const ForeachGuildCallbackType &callback) {
  if (!callback) {
    return;
  }

  for (const auto &it : guild_set_) {
    callback(it);
  }
}

}  // namespace guild_service